import { ExtractionTask, ExtractionResult, ParserConfig } from '../types';
import { AndroidParser } from '../parsers/AndroidParser';
import { IosParser } from '../parsers/IosParser';
import { WebParser } from '../parsers/WebParser';
import { JavaParser } from '../parsers/JavaParser';
import { EventEmitter } from 'events';
import * as fs from 'fs';
import * as path from 'path';
import { logger } from '../utils/logger';

export class ParserEngine extends EventEmitter {
  /**
   * 解析器映射表
   * 存储不同类型的解析器实例，键为解析器类型，值为解析器实例
   */
  private parsers: Map<string, any>;
  
  /**
   * 解析器配置
   * 包含解析器类型和相关选项
   */
  private configs: ParserConfig[];

  /**
   * 解析引擎构造函数
   * @param configs 解析器配置对象，定义了解析器类型和选项
   */
  constructor(configs: ParserConfig[]) {
    super();
    this.configs = configs;
    this.parsers = new Map();
    logger.info('初始化解析引擎', {
      配置数量: configs.length,
      配置列表: configs.map(c => ({ 类型: c.type, 解析器: c.parser }))
    });
    this.initializeParsers();
  }

  /**
   * 初始化解析器
   */
  private initializeParsers(): void {
    logger.info('开始初始化解析器', {
      已注册解析器: Array.from(this.parsers.keys())
    });

    // 注册所有配置的解析器
    for (const config of this.configs) {
      switch (config.type) {
        case 'android':
          this.parsers.set('android', new AndroidParser(config.options));
          logger.info('注册Android解析器', { 选项: config.options });
          break;
        case 'ios':
          this.parsers.set('ios', new IosParser(config.options));
          logger.info('注册iOS解析器', { 选项: config.options });
          break;
        case 'web':
          this.parsers.set('web', new WebParser(config.options));
          logger.info('注册Web解析器', { 选项: config.options });
          break;
        case 'java':
          this.parsers.set('java', new JavaParser());
          logger.info('注册Java解析器');
          break;
        default:
          logger.warn('未知的解析器类型', { 类型: config.type });
      }
    }

    logger.info('解析器初始化完成', {
      可用解析器: Array.from(this.parsers.keys())
    });
  }

  /**
   * 解析文件
   * @param filePath 文件路径
   * @param task 提取任务
   */
  public async parseFile(filePath: string, task: ExtractionTask): Promise<ExtractionResult> {
    try {
      // 1. 文件验证
      logger.info('开始解析文件', {
        文件路径: filePath,
        任务ID: task.taskId,
        项目ID: task.projectId
      });
      
      this.validateFile(filePath);
      
      // 2. 获取文件信息
      const stats = fs.statSync(filePath);
      logger.info('文件信息', {
        文件路径: filePath,
        文件大小: stats.size,
        创建时间: stats.birthtime,
        修改时间: stats.mtime
      });

      // 3. 获取文件类型
      const fileType = this.getFileType(filePath);
      logger.info('文件类型识别', {
        文件路径: filePath,
        识别类型: fileType,
        扩展名: path.extname(filePath)
      });
      
      // 4. 获取解析器
      const parser = this.parsers.get(fileType);
      if (!parser) {
        logger.error('未找到对应解析器', {
          文件类型: fileType,
          文件路径: filePath,
          可用解析器: Array.from(this.parsers.keys())
        });
        throw new Error(`No parser found for file type: ${fileType}`);
      }

      // 5. 读取文件内容
      logger.info('开始读取文件内容', { filePath });
      const content = await fs.promises.readFile(filePath, 'utf-8');
      logger.info('文件内容读取完成', {
        文件路径: filePath,
        内容长度: content.length
      });

      // 6. 解析文件
      logger.info('开始解析内容', {
        文件路径: filePath,
        解析器类型: fileType
      });

      const result = await parser.parse(content, {
        filePath,
        task,
        config: this.configs.find(c => c.type === fileType)
      });

      // 7. 解析完成
      logger.info('解析完成', {
        文件路径: filePath,
        状态: result.status,
        提取键数: Object.keys(result.translations).length,
        统计信息: result.statistics
      });

      // 触发解析完成事件
      this.emit('parseCompleted', {
        filePath,
        result
      });

      return result;

    } catch (error) {
      // 8. 错误处理
      logger.error('解析失败', {
        文件路径: filePath,
        错误类型: error instanceof Error ? error.constructor.name : typeof error,
        错误消息: error instanceof Error ? error.message : String(error),
        错误堆栈: error instanceof Error ? error.stack : undefined,
        解析器状态: {
          可用解析器: Array.from(this.parsers.keys()),
          配置列表: this.configs.map(c => ({ 类型: c.type, 解析器: c.parser }))
        }
      });

      // 触发解析错误事件
      this.emit('parseError', {
        filePath,
        error: error as Error
      });

      throw error;
    }
  }

  /**
   * 获取文件类型
   * @param filePath 文件路径
   */
  private getFileType(filePath: string): string {
    const ext = path.extname(filePath).toLowerCase();
    
    switch (ext) {
      case '.xml':
        return 'android';
      case '.strings':
        return 'ios';
      case '.js':
      case '.ts':
      case '.vue':
      case '.jsx':
      case '.tsx':
        return 'web';
      case '.java':
        return 'java';
      default:
        logger.warn('不支持的文件类型', {
          文件路径: filePath,
          扩展名: ext,
          支持类型: ['.xml', '.strings', '.js', '.ts', '.vue', '.jsx', '.tsx', '.java']
        });
        throw new Error(`Unsupported file type: ${ext}`);
    }
  }

  /**
   * 验证文件
   * @param filePath 文件路径
   */
  private validateFile(filePath: string): void {
    logger.info('验证文件', { filePath });

    if (!fs.existsSync(filePath)) {
      logger.error('文件不存在', { filePath });
      throw new Error(`File not found: ${filePath}`);
    }

    const stats = fs.statSync(filePath);
    if (!stats.isFile()) {
      logger.error('路径不是文件', { 
        文件路径: filePath,
        文件类型: stats.isDirectory() ? 'directory' : 'other'
      });
      throw new Error(`Path is not a file: ${filePath}`);
    }

    logger.info('文件验证通过', { 
      文件路径: filePath,
      文件大小: stats.size
    });
  }
} 